package com.cfjjc.gz.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期时间工具类 <br>
 * 提供一些常用的日期时间操作方法，所有方法都为静态，不用实例化该类即可使用。 <br>
 */

public class DateTimeUtil {

	/**
	 * 缺省的日期显示格式： yyyy-MM-dd
	 */
	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

	/**
	 * 缺省的日期时间显示格式：yyyy-MM-dd HH:mm:ss
	 */
	public static final String DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	
	/**
	 * 日期时间显示格式(精确到毫秒)：yyyyMMddHHmmssSSS
	 */
	public static final String TIMESTAMP_FORMAT = "yyyyMMddHHmmssSSS";
	
	/**
	 * 私有构造方法，禁止对该类进行实例化
	 */
	private DateTimeUtil() {
	}

	/**
	 * 得到系统当前日期时间
	 * 
	 * @return 当前日期时间
	 */
	public static Date getNow() {
		return Calendar.getInstance().getTime();
	}

	/**
	 * 得到用缺省方式格式化的当前日期
	 * 
	 * @return 当前日期
	 */
	public static String getDate() {
		return getDateTime(DEFAULT_DATE_FORMAT);
	}

	/**
	 * 得到当前日期的中文日期格式,如2005年01月01日
	 */
	public static String getDate_zh() {
		return getDate_zh(getDate());
	}

	/**
	 * 得到指定日期的中文日期格式,如2005年01月01日
	 */
	public static String getDate_zh(String datestr) {
		return getDate_zh(datestr, DEFAULT_DATE_FORMAT);
	}

	/**
	 * 得到指定日期的中文日期格式,如2005年01月01日
	 */
	public static String getDate_zh(String datestr, String pattern) {
		Date date = parse(datestr, pattern);
		Calendar calendar = Calendar.getInstance();

		calendar.setTime(date);
		return calendar.get(Calendar.YEAR) + "年"
				+ (calendar.get(Calendar.MONTH) + 1) + "月"
				+ calendar.get(Calendar.DATE) + "日";
	}

	/**
	 * 得到用缺省方式格式化的当前日期及时间
	 * 
	 * @return 当前日期及时间
	 */
	public static String getDateTime() {
		return getDateTime(DEFAULT_DATETIME_FORMAT);
	}

	/**
	 * 得到系统当前日期及时间，并用指定的方式格式化
	 * 
	 * @param pattern
	 *            显示格式
	 * @return 当前日期及时间
	 */
	public static String getDateTime(String pattern) {
		Date datetime = Calendar.getInstance().getTime();
		return getDateTime(datetime, pattern);
	}

	/**
	 * 得到用缺省方式格式化的日期
	 * 
	 * @param date
	 *            需要进行格式化的日期
	 * @return 日期时间字符串
	 */
	public static String getDateTime(Date date) {
		return getDateTime(date, null);
	}

	/**
	 * 得到用指定方式格式化的日期
	 * 
	 * @param date
	 *            需要进行格式化的日期
	 * @param pattern
	 *            显示格式
	 * @return 日期时间字符串
	 */
	public static String getDateTime(Date date, String pattern) {
		if (null == pattern || "".equals(pattern)) {
			pattern = DEFAULT_DATETIME_FORMAT;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		return dateFormat.format(date);
	}

	/**
	 * 得到当前年份
	 * 
	 * @return 当前年份
	 */
	public static int getCurrentYear() {
		return Calendar.getInstance().get(Calendar.YEAR);

	}

	/**
	 * 得到当前分钟
	 * 
	 * @return 当前分钟
	 */
	public static int getCurrentMinute() {
		return Calendar.getInstance().get(Calendar.MINUTE);
	}

	/**
	 * 得到当前小时
	 * 
	 * @return 当前小时
	 */
	public static int getCurrentHour() {
		return Calendar.getInstance().get(Calendar.HOUR);

	}

	/**
	 * 得到当前秒
	 * 
	 * @return 当前秒
	 */
	public static int getCurrentSecond() {
		return Calendar.getInstance().get(Calendar.SECOND);

	}

	/**
	 * 得到当前月份
	 * 
	 * @return 当前月份
	 */
	public static int getCurrentMonth() {
		// 用get得到的月份数比实际的小1，需要加上
		return Calendar.getInstance().get(Calendar.MONTH) + 1;
	}

	/**
	 * 得到当前日
	 * 
	 * @return 当前日
	 */
	public static int getCurrentDay() {
		return Calendar.getInstance().get(Calendar.DATE);
	}

	/**
	 * 取得当前日期以后若干天的日期。如果要得到以前的日期，参数用负数。 例如要得到上星期同一天的日期，参数则为-7
	 * 
	 * @param days
	 *            增加的日期数
	 * @return 增加以后的日期
	 */
	public static Date addDays(int days) {
		return add(getNow(), days, Calendar.DATE);
	}

	/**
	 * 取得指定日期以后若干天的日期。如果要得到以前的日期，参数用负数。
	 * 
	 * @param date
	 *            基准日期
	 * @param days
	 *            增加的日期数
	 * @return 增加以后的日期
	 */
	public static Date addDays(Date date, int days) {
		return add(date, days, Calendar.DATE);
	}

	/**
	 * 取得指定日期以后若干天的日期。如果要得到以前的日期，参数用负数。
	 * 
	 * @param date
	 *            基准日期，格式为“yyyy-MM-dd”形式。
	 * @param days
	 *            增加的日期数
	 * @return 增加以后的日期
	 */
	public static Date addDays(String date, int days) {

		Date date1 = DateTimeUtil.parse(date, "yyyy-MM-dd");// 格式化日期

		return add(date1, days, Calendar.DATE);
	}

	/**
	 * 取得当前日期以后某月的日期。如果要得到以前月份的日期，参数用负数。
	 * 
	 * @param months
	 *            增加的月份数
	 * @return 增加以后的日期
	 */
	public static Date addMonths(int months) {
		return add(getNow(), months, Calendar.MONTH);
	}

	/**
	 * 取得指定日期以后某月的日期。如果要得到以前月份的日期，参数用负数。 注意，可能不是同一日子，例如2003-1-31加上一个月是2003-2-28
	 * 
	 * @param date
	 *            基准日期
	 * @param months
	 *            增加的月份数
	 * @return 增加以后的日期
	 */
	public static Date addMonths(Date date, int months) {
		return add(date, months, Calendar.MONTH);
	}

	/**
	 * 内部方法。为指定日期增加相应的天数或月数
	 * 
	 * @param date
	 *            基准日期
	 * @param amount
	 *            增加的数量
	 * @param field
	 *            增加的单位，年，月或者日
	 * @return 增加以后的日期
	 */
	private static Date add(Date date, int amount, int field) {
		Calendar calendar = Calendar.getInstance();

		calendar.setTime(date);
		calendar.add(field, amount);

		return calendar.getTime();
	}

	/**
	 * 计算两个日期相差天数。 用第一个日期减去第二个。如果前一个日期小于后一个日期，则返回负数
	 * 
	 * @param one
	 *            第一个日期数，作为基准
	 * @param two
	 *            第二个日期数，作为比较
	 * @return 两个日期相差天数
	 */
	public static long diffDays(Date one, Date two) {
		return (one.getTime() - two.getTime()) / (24 * 60 * 60 * 1000);
	}

	/**
	 * 计算两个日期相差月份数 如果前一个日期小于后一个日期，则返回负数
	 * 
	 * @param one
	 *            第一个日期数，作为基准
	 * @param two
	 *            第二个日期数，作为比较
	 * @return 两个日期相差月份数
	 */
	public static int diffMonths(Date one, Date two) {

		Calendar calendar = Calendar.getInstance();

		// 得到第一个日期的年分和月份数
		calendar.setTime(one);
		int yearOne = calendar.get(Calendar.YEAR);
		int monthOne = calendar.get(Calendar.MONDAY);

		// 得到第二个日期的年份和月份
		calendar.setTime(two);
		int yearTwo = calendar.get(Calendar.YEAR);
		int monthTwo = calendar.get(Calendar.MONDAY);

		return (yearOne - yearTwo) * 12 + (monthOne - monthTwo);
	}

	/**
	 * 将一个字符串用给定的格式转换为日期类型。 <br>
	 * 注意：如果返回null，则表示解析失败
	 * 
	 * @param datestr
	 *            需要解析的日期字符串
	 * @param pattern
	 *            日期字符串的格式，默认为“yyyy-MM-dd”的形式
	 * @return 解析后的日期
	 */
	public static Date parse(String datestr, String pattern) {
		Date date = null;

		if (null == pattern || "".equals(pattern)) {
			pattern = DEFAULT_DATE_FORMAT;
		}

		try {
			SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
			date = dateFormat.parse(datestr);
		} catch (ParseException e) {
			//
		}

		return date;
	}

	/**
	 * 返回本月的第一天
	 * 
	 * @return 本月第一天的日期
	 */
	public static String getMonthFirstDay() {
		String date = getDate();
		date = date.substring(0, 8);
		date += "01";
		return date;
	}

	/**
	 * 得到本年第一天
	 * 
	 * @return
	 */
	public static String getYearFirstDay() {
		int year = getCurrentYear();
		return String.valueOf(year) + "-01-01";
	}

	/**
	 * 得到本年最后一天
	 * 
	 * @return
	 */
	public static String getYearLastDay() {
		int year = getCurrentYear();
		return String.valueOf(year) + "-12-31";
	}

	/**
	 * 返回本月的最后一天
	 * 
	 * @return 本月最后一天的日期
	 */
	public static String getMonthLastDay() {
		return getDateTime(getMonthLastDay(getNow()), "yyyy-MM-dd");
	}

	/**
	 * 返回给定日期中的月份中的最后一天
	 * 
	 * @param date
	 *            基准日期
	 * @return 该月最后一天的日期
	 */
	public static Date getMonthLastDay(Date date) {

		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		// 将日期设置为下一月第一天
		calendar.set(calendar.get(Calendar.YEAR),
				calendar.get(Calendar.MONTH) + 1, 1);

		// 减去1天，得到的即本月的最后一天
		calendar.add(Calendar.DATE, -1);

		return calendar.getTime();
	}

	public static void main(String[] args) {
//		String test = "2003-2-1";
//		Date date;
//		try {
//			date = parse(test, "");
//
//			System.out.println("得到当前日期 － getDate():" + DateTimeUtil.getDate());
//			System.out.println("得到当前日期时间 － getDateTime():"
//					+ DateTimeUtil.getDateTime());
//
//			System.out.println("得到当前年份 － getCurrentYear():"
//					+ DateTimeUtil.getCurrentYear());
//			System.out.println("得到当前月份 － getCurrentMonth():"
//					+ DateTimeUtil.getCurrentMonth());
//			System.out.println("得到当前日子 － getCurrentDay():"
//					+ DateTimeUtil.getCurrentDay());
//
//			System.out.println("解析 － parse(" + test + "):"
//					+ getDateTime(date, "yyyy-MM-dd"));
//
//			System.out.println("自增月份 － addMonths(3):"
//					+ getDateTime(addMonths(3), "yyyy-MM-dd"));
//			System.out.println("增加月份 － addMonths(" + test + ",3):"
//					+ getDateTime(addMonths(date, 3), "yyyy-MM-dd"));
//			System.out.println("增加日期 － addDays(" + test + ",3):"
//					+ getDateTime(addDays(date, 3), "yyyy-MM-dd"));
//			System.out.println("自增日期 － addDays(3):"
//					+ getDateTime(addDays(3), "yyyy-MM-dd"));
//
//			System.out.println("比较日期 － diffDays():"
//					+ DateTimeUtil.diffDays(DateTimeUtil.getNow(), date));
//			System.out.println("比较月份 － diffMonths():"
//					+ DateTimeUtil.diffMonths(DateTimeUtil.getNow(), date));
//
//			System.out.println("得到" + test + "所在月份的最后一天:"
//					+ getDateTime(getMonthLastDay(date), "yyyy-MM-dd"));
//			System.out.println("得到本月第一天:" + getMonthFirstDay());
//			System.out.println("得到当前日期的中文格式:" + getDate_zh());
//			System.out.println("得到" + test + "的中文格式:" + getDate_zh(test));
//		} catch (Exception e) {
//			System.out.println(e.getStackTrace());
//		}
		
		// 方法一：
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date now = null;
		Date date = null;
		try {
		now = df.parse("2004-03-03 13:31:40");
		date = df.parse("2004-03-02 11:30:24");
		} catch (ParseException e) {
		e.printStackTrace();
		}

		long l = now.getTime() - date.getTime();
		long day = l / (24 * 60 * 60 * 1000);
		long hour = (l / (60 * 60 * 1000));
		long min = ((l / (60 * 1000))  - hour * 60);
		long s = (l / 1000  - hour * 60 * 60 - min * 60);
		System.out.println("" + hour + "小时" + min + "分" + s + "秒");

		// 方法二：
		SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date begin = null;
		Date end = null;
		try {
		begin = dfs.parse("2004-01-02 11:30:24");
		end = dfs.parse("2004-03-26 13:31:40");
		} catch (ParseException e) {
		e.printStackTrace();
		}

		long between = (end.getTime() - begin.getTime()) / 1000;// 除以1000是为了转换成秒

		long day1 = between / (24 * 3600);
		long hour1 = between % (24 * 3600) / 3600;
		long minute1 = between % 3600 / 60;
		long second1 = between % 60;
		System.out.println("" + day1 + "天" + hour1 + "小时" + minute1 + "分"
		+ second1 + "秒");
		
		DateTimeUtil dtu = new DateTimeUtil();
		System.out.println(dtu.getDateTime("yyyyMMddHHmmssSSSS"));

	}

	/**
	 * 把日期字符转换成标准的格式。“YYYY-MM-DD”
	 * 
	 * @param data_str
	 * @return
	 */
	public static String parseDataStr(String data_str) {
		String[] dateStr = data_str.split("-");
		if (dateStr.length != 3) {
			return data_str;
		}
		if (dateStr[1].length() == 1) {
			dateStr[1] = "0" + dateStr[1];
		}
		if (dateStr[2].length() == 1) {
			dateStr[2] = "0" + dateStr[2];
		}
		return dateStr[0] + "-" + dateStr[1] + "-" + dateStr[2];
	}

	/**
	 * 取得前一天日期的字符串
	 * 
	 * @param aaz007
	 * @return
	 */
	public static String reduceOneDay(String aaz007) {
		// 如果为空则直接返回
		if (aaz007 == null || aaz007.equals("")) {
			return "";
		}
		// 以默认格式把字符串转换成为日期类型
		Date date = DateTimeUtil.parse(aaz007, null);
		// 然后把日期减一天
		date = DateTimeUtil.addDays(date, -1);
		// 最后返回减一天的日期的字符串
		return DateTimeUtil.getDateTime(date, DEFAULT_DATE_FORMAT);
	}
	
	/**
	 * 根据给定的日期，取得下一天日期的字符串
	 * 
	 * @param dateStr
	 * @return
	 */
	public static String addOneDay(String dateStr) {
		// 如果为空则直接返回
		if (dateStr == null || dateStr.equals("")) {
			return "";
		}
		// 以默认格式把字符串转换成为日期类型
		Date date = DateTimeUtil.parse(dateStr, null);
		// 然后把日期加一天
		date = DateTimeUtil.addDays(date, 1);
		// 最后返回加一天的日期的字符串
		return DateTimeUtil.getDateTime(date, DEFAULT_DATE_FORMAT);
	}

	// 取得当前日期的前30天的日期字符串
	public static String reduceThirtyDays() {
		return getDateTime(addDays(getNow(), -30), DEFAULT_DATE_FORMAT);
	}
	
	/**
	 * 比较起始日期、终止日期、系统日期三个日期字符串，返回最大一个日期字符串.
	 * 
	 * <p>说明: 终止日期字符串可以为空。
	 * @param fqsrq 起始日期
	 * @param fzzrq 终止日期
	 * @param sysDate 系统日期
	 * @return 返回最大的日期字符串
	 */
	public static String maxDate(String fqsrq, String fzzrq, String sysDate ) {
		
		String max = "";
		if (fqsrq.compareTo(sysDate) >= 0) {
			max = fqsrq;
		} else {
			max = sysDate;
		}
		
		if (fzzrq != null && !"".equals(fzzrq)) {
			if (max.compareTo(fzzrq) < 0) {
				max = fzzrq;
			}
		}
		return max;
	}
}